home *** CD-ROM | disk | FTP | other *** search
/ Network Support Library / RoseWare - Network Support Library.iso / manage / gtree.arc / GTREE.C next >
C/C++ Source or Header  |  1988-03-17  |  14KB  |  392 lines

  1. /**********************************************************************/
  2. /*                                                        */
  3. /*    GTREE.C                                                */
  4. /*                                                        */
  5. /*    This will search an entire drive and print a graphical picture    */
  6. /*    of the tree structure of its directories.                    */
  7. /*                                                        */
  8. /**********************************************************************/
  9. /*                                                        */
  10. /*    Written    October 21, 1985                                */
  11. /*                                                        */
  12. /*    Author    David Midkiff -- D. M. Software And Systems            */
  13. /*                                                        */
  14. /**********************************************************************/
  15. /*                                                        */
  16. /*    Modified    December 13, 1986                                */
  17. /*            David Midkiff -- D. M. Software And Systems            */
  18. /*            Added the ability to delete the specified files.        */
  19. /*                                                        */
  20. /**********************************************************************/
  21. /*                                                        */
  22. /*    Modified    January 29, 1987                                */
  23. /*            David Midkiff -- D. M. Software And Systems            */
  24. /*            Changed the delete function to ask for operator        */
  25. /*            verification beforing deleting files, and the -v        */
  26. /*            command line switch to "pre"-verify deletions.        */
  27. /*                                                        */
  28. /**********************************************************************/
  29. /*                                                        */
  30. /*    Modified    December 1, 1987                                */
  31. /*            David Midkiff -- D. M. Software And Systems            */
  32. /*            This code was ported from the Lattice C compiler to    */
  33. /*            Turbo C.                                        */
  34. /*                                                        */
  35. /**********************************************************************/
  36. /*                                                        */
  37. /*    Modified    December 23, 1987                                */
  38. /*            David Midkiff -- D. M. Software And Systems            */
  39. /*            This was becoming unmanagable and unusable, so I        */
  40. /*            took the code from HUNT.C and moved it to here so I    */
  41. /*            could just print a reasonable tree and created two    */
  42. /*            programs from HUNT.  These are GTREE and HUNT.        */
  43. /*                                                        */
  44. /**********************************************************************/
  45. /*                                                        */
  46. /*    Copyright (c) 1988 -- D. M. Software And Systems                */
  47. /*                                                        */
  48. /*    All rights reserved.  Do not redistribute this program without    */
  49. /*    this notice, or the notice in the main() function.            */
  50. /*                                                        */
  51. /*    This program is designed to be instructive and useful, however    */
  52. /*    there are no warranties expressed or implied.  Feel free to        */
  53. /*    use this program in any manner you see fit, with the exceptions    */
  54. /*    of commerical environments and redistribution for any fee.        */
  55. /*    You are feel free to redistribute this program to any bulletin    */
  56. /*    boards or user's group, provide no fee is charge for any service    */
  57. /*    you may provide.                                        */
  58. /*                                                        */
  59. /*    If you find this program useful, you are asked to send a $20    */
  60. /*    contribution towards its upkeep.  No support will be given to    */
  61. /*    unsupported users, except in the cases where the user needs to    */
  62. /*    find out if this program is suitable for his or her purposes.    */
  63. /*                                                        */
  64. /*    Send $20.00 contribution to:                                */
  65. /*        D. M. Software And Systems                            */
  66. /*        6572 Suson Woods Drive                                */
  67. /*        St. Louis, MO  63128                                */
  68. /*                                                        */
  69. /*    Remember, you do not have to send a contribution, but your        */
  70. /*    conscience will haunt you forever.                            */
  71. /*                                                        */
  72. /**********************************************************************/
  73.  
  74.  
  75. #include "stdio.h"
  76. #include "conio.h"
  77. #include "ctype.h"
  78. #include "dir.h"
  79. #include "dos.h"
  80. #include "io.h"
  81. #include "stdlib.h"
  82. #include "string.h"
  83.  
  84. extern unsigned _stklen = 32678U ;        /* Need a larger than normal stack */
  85.                                 /* since buildtree() is recursive. */
  86.  
  87. /*PAGE*/
  88. /*******************************************************/
  89. /*                                            */
  90. /*        --- GLOBAL VARIABLE DEFINITIONS ---        */
  91. /*                                            */
  92. /*******************************************************/
  93.  
  94. static int lenflags[21] =            /* Length of each level's name  */
  95.             { 4 } ;                /* Root name's length */
  96. static int moreflags[21] ;             /* 1 == Level has more to print */
  97.  
  98. struct DIRDATA {
  99.     char name[65] ;                /* Directory's entire path name */
  100.     char thisname[65] ;                /* This directory's name */
  101.     struct DIRDATA *list ;            /* Beginning of list  for this level */
  102.     struct DIRDATA *next ;            /* Pointer to nest directory */
  103.     struct DIRDATA *node ;            /* Pointer to previous node level */
  104.     int level ;                    /* How deeply nested we are with this directory */
  105.     } ;
  106.     
  107. char corner = '┐' ;                    /* Corner character for line drawings */
  108.  
  109. int drive = -1 ;                    /* Drive to use as a default */
  110.  
  111. char horizontal_line = '─' ;            /* Horizontal line character for line drawings */
  112.  
  113. char left_chr = '├' ;                /* For when a level is continued */
  114.  
  115. char left_corner = '└' ;                /* For the last file in a level */
  116.  
  117. #define NSP (struct DIRDATA *) 0        /* Null Structure pointer for DIRDATA */
  118.     
  119. struct DIRDATA root ;                /* For the root directory */
  120.  
  121. char scratch[256] ;                    /* A scratch string */
  122.  
  123. #define SPACE ' '                    /* A space character */
  124.  
  125. char vertical_line = '│' ;            /* Vertical line character for line drawings */
  126.  
  127. /*PAGE*/
  128. /***********************************/
  129. /*                            */
  130. /*        FUNCTION PROTOTYPES        */
  131. /*                            */
  132. /***********************************/
  133.  
  134. void buildtree( struct DIRDATA *thisdirectory ) ;
  135. void fatalerr( char *message , int useflag ) ;
  136. void print_tree( struct DIRDATA *pointlist ) ;
  137. void showusage( void ) ;
  138. void strupper( char *destination , char *source ) ;
  139.  
  140. /*PAGE*/
  141. /**********************************************************************/
  142. /*                                                        */
  143. /*    BUILDTREE() - Build a directory tree from the passed name.       */
  144. /*                Care should be used when changing this            */
  145. /*                routine!!!!  It works as it stands now.            */
  146. /*                                                        */
  147. /**********************************************************************/
  148.  
  149. void buildtree( p )
  150.     struct DIRDATA *p ;                /* Directory being searched */
  151. {
  152.  
  153.     struct ffblk dir ;                /* For a directories information */
  154.     static int nestedlevel  = 0 ;        /* How deeply nested we are */
  155.     struct DIRDATA *new ;            /* For any directory found */
  156.     char newname[81] ;                /* String for formatting a name */
  157.     struct DIRDATA *t ;                /* A scratch pointer */
  158.     static int lastlevel = 0 ;        /* Last level with a file added */
  159.     static struct DIRDATA *lastone = &root ;
  160.  
  161.     (void) sprintf( newname , "%s*.*" , p->name ) ;
  162.     if( !findfirst( newname , &dir , FA_DIREC ) )
  163.     {
  164.         do
  165.         {
  166.             if( dir.ff_attrib == FA_DIREC && dir.ff_name[0] != '.' )
  167.             {
  168.                 (void) sprintf( newname , "%s%s\\" , p->name , dir.ff_name ) ;
  169.                 if( (new=malloc((unsigned)sizeof(struct DIRDATA))) == NULL )
  170.                     fatalerr( "Out of memory during tree allocation" , 0 ) ;
  171.                 /***************************************/
  172.                 /* Initialize the new structure's data */
  173.                 /***************************************/
  174.                  new->node = new->list = new->next = NSP ;
  175.                 new->level = nestedlevel ;
  176.                 (void) strcpy( new->thisname , dir.ff_name ) ;
  177.                 (void) strcpy( new->name , newname ) ;
  178.                 if( nestedlevel > lastlevel )            /*****************************/
  179.                 {                                /* First file in a new level */
  180.                     new->node = lastone ;            /*****************************/
  181.                     lastone->next = new ;
  182.                     lastone = new ;
  183.                 }    /* if( nestedlevel > lastlevel ) */
  184.                 if( nestedlevel == lastlevel )        /*****************************/
  185.                 {                                /* Next file in same level   */
  186.                     new->node = lastone ;            /*****************************/
  187.                     lastone->list = new ;
  188.                     lastone = new ;
  189.                 }    /* if( nestedlevel == lastlevel ) */
  190.                 if( nestedlevel < lastlevel )            /*****************************/
  191.                 {                                /* Back to a previous level  */
  192.                     t = lastone ;                    /*****************************/
  193.                     while( t->level > nestedlevel )
  194.                         t = t->node ;
  195.                     while( t->list != NSP )
  196.                         t = t->list ;
  197.                     t->list = new ;
  198.                     new->node = t ;
  199.                     lastone = new ;
  200.                 }    /* if( nextedlevel < lastlevel ) */
  201.                 lastlevel = nestedlevel++ ;
  202.                 buildtree( new ) ;
  203.             }    /* if( dir.ff_attrib == FA_DIREC && dir.ff_name[0] != '.' ) */
  204.         } while( !findnext( &dir ) ) ;
  205.     }    /* if( !findfirst( newname , dir , FA_DIREC ) ) */
  206.  
  207.     nestedlevel-- ;
  208.         
  209.     return ;
  210.     
  211. }    /* end of buildtree() */
  212.  
  213. /*PAGE*/
  214. /**********************************************************************/
  215. /*                                                        */
  216. /*    FATALERR() - Print a fatal error message and exit after setting    */
  217. /*               the DOS ERRORLEVEL variable to 1.                */
  218. /*                                                        */
  219. /**********************************************************************/
  220.  
  221. void fatalerr( msg , useflag )
  222.     char *msg ;                /* Part of error message to print */
  223.     int useflag ;                /* 1 == Show usage before exiting */
  224. {
  225.  
  226.     printf( "\n %s -- GTREE canceled\n" , msg ) ;
  227.     if( useflag )
  228.         showusage() ;
  229.         
  230.     exit( 1 ) ;
  231.     
  232.     return ;        /* sic */
  233.     
  234. }    /* end of fatal error */
  235.  
  236. /*page*/
  237. /**********************************************************************/
  238. /*                                                        */
  239. /*    MAIN() -    This is the main processing function.  The only things    */
  240. /*                that are processed here are command line parameters.    */
  241. /*            The process is:                                */
  242. /*                1.) Process command line arguements.            */
  243. /*                2.) Check for a drive assignment.  If not present    */
  244. /*                    use the default drive.                    */
  245. /*                3.) Format the root file name by inserting the    */
  246. /*                    drive letter to give C:\, for example.        */
  247. /*                4.) Call the buildtree() function with the root    */
  248. /*                    directory to get started.                    */
  249. /*                                                        */
  250. /**********************************************************************/
  251.  
  252. void main( argc , argv )
  253.     int argc ;
  254.     char *argv[] ;
  255. {
  256.  
  257.     int i ;                        /* A scratch integer */
  258.  
  259.     (void) puts( "GTREE -- Version 1.0 -- March 1988\nCopyright (c) 1988.  D. M. Software and Systems.  All rights reserved." ) ;
  260.  
  261.     for( i=1; i<argc; i++ )                    /* Parse the command line arguments */
  262.     {
  263.         if( *argv[i] != '-' && *argv[i] != '/' )
  264.         {
  265.             if( *(argv[i]+1) != ':' )
  266.                 fatalerr( "Invalid command line switch" , 1 ) ;
  267.             else
  268.                 drive = toupper( *argv[i] ) - 'A' ;
  269.         }
  270.         else    
  271.         {
  272.             if( tolower( *(argv[i]+1) ) == 'g' )
  273.             {
  274.                 left_corner = left_chr = corner = '+' ;
  275.                 vertical_line = '|' ;
  276.                 horizontal_line = '-' ;
  277.             }
  278.             else        /* Invalid switch */
  279.             {
  280.                 (void) sprintf( scratch , "%s is an invalid parameter" , argv[i] ) ;
  281.                 fatalerr( scratch , 0 ) ;    
  282.             }    /* if( tolower( *(argv[i]+1) ) == 'g' ) */
  283.         }    /* if( *argv[i] != '-' && *argv[i] != '/' ) */
  284.     }    /* for( i=1; iargc; i++ ) */
  285.     
  286.     if( drive == -1 )                            /* Set drive to the current drive */
  287.         drive = getdisk() ;                        /* of not set by the operator.    */
  288.         
  289.     drive += 'A' ;                                /* Convert to alpha */
  290.             
  291.     (void) sprintf( root.name , "%c:\\" , drive ) ;    /* Format for buildtree()'s initial call */
  292.     root.level = 0 ;
  293.     root.node = root.next = root.list = NSP ;
  294.  
  295.     buildtree( &root ) ;
  296.     
  297.     if( root.next == NSP && root.list == NSP )
  298.     {
  299.         printf( "\n\nThere where no directories after %s" , root.name ) ;
  300.         return ;
  301.     }    /* if( root->nest == NSP && root->list == NSP ) */
  302.     
  303.     printf( "\n%s%c%c\n" , root.name , horizontal_line , corner ) ;
  304.     print_tree( root.list ) ;
  305.     
  306.     exit( 0 ) ;
  307.     
  308. }    /* end of main() */
  309.  
  310.  
  311. /**********************************************************************/
  312. /*                                                        */
  313. /*    PRINT_TREE() - This will print the tree.  It is not part of the    */
  314. /*                    buildtree() function the grahpics characters that    */
  315. /*                are used.  There is a look ahead problem that is    */
  316. /*                associated with all of the connectors.            */
  317. /*                                                        */
  318. /*                WARNING - This function, like buildtree() is        */
  319. /*                        recursive.  Use care when changing.    */
  320. /*                                                        */
  321. /**********************************************************************/
  322.  
  323. void print_tree( p )
  324.     struct DIRDATA *p ;
  325. {
  326.     int i ;                            /* Scratch integer */
  327.     int j ;                            /* Scratch integer */
  328.  
  329.     do
  330.     {
  331.         moreflags[p->level] = ( p->list != NSP ) ;
  332.  
  333.         /***********************************************************/
  334.         /* Indent this line for each level and draw the connectors */
  335.         /* unless this is the current level or this one is empty.  */
  336.         /***********************************************************/
  337.         for( i=0; i<=p->level; i++ )
  338.         {
  339.             for( j=0; j<lenflags[i]; j++ )
  340.                 putchar( SPACE ) ;
  341.             if( i != p->level )
  342.                 putchar( (moreflags[i]) ? vertical_line : SPACE ) ;
  343.         }    /* for( i=0; i<=p->level; i++ ) */
  344.         
  345.         printf( "%c%c%s" , (moreflags[p->level]!=0) ? left_chr : left_corner , horizontal_line , p->thisname ) ;
  346.  
  347.         lenflags[p->level+1] = strlen( p->thisname ) + 2 ;    /* Include line character */
  348.  
  349.         /****************************************/
  350.         /* Is there another level from here ?   */
  351.         /* If so, print a connector and call    */
  352.         /* print_tree() again with the next one */
  353.         /****************************************/
  354.         if( p->next != NSP )
  355.         {
  356.             printf( "%c%c\n" , horizontal_line , corner ) ;
  357.             print_tree( p->next ) ;
  358.         }    /* if( p->next != NSP ) */
  359.         else    
  360.             (void) puts( "" ) ;                            /* Forced line feed */
  361.         p  = p->list ;
  362.     } while( p != NSP ) ;
  363.     
  364.     return ;
  365.     
  366. }    /* end of print_tree() */
  367.  
  368. /**********************************************************************/
  369. /*                                                        */
  370. /*    SHOWUSAGE() - Prints the usage message that appears at runtime.    */
  371. /*                This will be called by certain errors from         */
  372. /*                the fatalerr() routine above.                    */
  373. /*                                                        */
  374. /**********************************************************************/
  375.  
  376. void showusage()
  377. {
  378.  
  379.     (void) puts( "\nUsage is hunt [drive:] [-g] where:" ) ;
  380.     (void) puts( "\tdrive: overrides the default drive specification." ) ;
  381.     (void) puts( "\t-G for graphics.  Suppresses graphics characters during display." ) ;
  382.     
  383.     return ;
  384.     
  385. }    /* end of showusage() */
  386.  
  387.  
  388. /*************************/
  389. /*                    */
  390. /*    END OF GTREE.C        */
  391. /*                    */
  392. /*************************/